package vip.xiaomaoxiaoke.msg.repository.impl;

import vip.xiaomaoxiaoke.msg.repository.LocalMessageRepository;
import vip.xiaomaoxiaoke.msg.repository.LocalMessageTable;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;
import java.util.List;


public class JdbcTemplateBasedLocalMessageRepository implements LocalMessageRepository {
    private static final String SQL_INSERT =
            "INSERT INTO %s " +
                    "(msg_id, orderly, retry_count, application_name, sharding_key, " +
                    "time_interval, max_retries, state, response_content, " +
                    "refusal_strategies_state, body) " +
                    "VALUES " +
                    "(:msgId, :orderly, :retryCount, :applicationName, :shardingKey, " +
                    ":timeInterval, :maxRetries, :state, :responseContent, " +
                    ":refusalStrategiesState, :body)";
    private static final String SQL_UPDATE =
            "UPDATE %s " +
                    "SET " +
                    "  retry_count = :retryCount, " +
                    "  state = :state, " +
                    "  response_content = :responseContent, " +
                    "  refusal_strategies_state = :refusalStrategiesState, " +
                    "  body = :body " +
                    "WHERE " +
                    "  id = :id";

    // 修改了查询SQL，匹配MySqlLocalMessageRepositoryImpl的逻辑
    private static final String SQL_LOAD_NOT_SUCCESS_BY_ID_GT =
            "SELECT " +
                    "  id, " +
                    "  orderly, " +
                    "  sharding_key AS shardingKey, " +
                    "  msg_id AS msgId, " +
                    "  body AS body, " +
                    "  state AS state, " +
            "  create_time AS createTime, " +
            "  update_time AS updateTime, " +
            "  application_name AS applicationName, " +
            "  retry_count AS retryCount, " +
            "  max_retries AS maxRetries, " +
            "  refusal_strategies_state AS refusalStrategiesState, " +
            "  response_content AS responseContent " +
            "FROM %s " +
            "WHERE id > :id " +
            "  AND state != 1 " +
            "  AND application_name = :applicationName " +
            "  AND retry_count <= max_retries " +
            "ORDER BY id ASC " +
            "LIMIT :size";

    private final TransactionTemplate transactionTemplate;
    private final NamedParameterJdbcTemplate jdbcTemplate;
    private final String tableName;
    private final RowMapper<LocalMessageTable> rowMapper;

    public JdbcTemplateBasedLocalMessageRepository(
            DataSource dataSource,
            PlatformTransactionManager transactionManager, // 👈 注入 Spring 的事务管理器
            String tableName) {

        this.transactionTemplate = new TransactionTemplate(transactionManager); // ✅ 使用容器的 TM
        this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
        this.tableName = tableName;
        this.rowMapper = new BeanPropertyRowMapper<>(LocalMessageTable.class);
    }



    @Override
    public void save(LocalMessageTable message) {
        // 使用TransactionTemplate确保操作在事务中
        transactionTemplate.execute(status -> {
            // 准备SQL，替换表名
            String insertSql = String.format(SQL_INSERT, tableName);
            // 创建参数源
            SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(message);
            // 使用KeyHolder获取插入的主键ID
            KeyHolder keyHolder = new GeneratedKeyHolder();
            // 执行插入
            jdbcTemplate.update(insertSql, parameterSource, keyHolder);
            // 将生成的主键ID设置回实体对象
            if (keyHolder.getKey() != null) {
                message.setId(keyHolder.getKey().longValue());
            }
            return null; // TransactionCallback不返回值
        });
    }

    @Override
    public void update(LocalMessageTable message) {
        // 使用TransactionTemplate确保操作在事务中
        transactionTemplate.execute(status -> {
            // 准备SQL，替换表名
            String updateSql = String.format(SQL_UPDATE, tableName);
            // 创建参数源
            SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(message);
            // 执行更新
            int updated = jdbcTemplate.update(updateSql, parameterSource);
            // 可以检查updated > 0来判断是否更新成功
            if (updated == 0) {
                // 可以选择抛出异常或记录日志，表示没有找到要更新的记录
                // throw new RuntimeException("Update failed, no record found with id: " + message.getId());
            }
            return null; // TransactionCallback不返回值
        });
    }

    @Override
    public List<LocalMessageTable> loadNotSuccessByUpdateGt(long id, int size) {
        // 准备SQL，替换表名
        String querySql = String.format(SQL_LOAD_NOT_SUCCESS_BY_ID_GT, tableName);
        // 创建参数源
        MapSqlParameterSource parameterSource = new MapSqlParameterSource();
        parameterSource.addValue("id", id);
        parameterSource.addValue("applicationName", "iot-starter"); // 硬编码，与MyBatis实现一致
        parameterSource.addValue("size", size); // LIMIT参数

        // 执行查询并返回结果列表
        return jdbcTemplate.query(querySql, parameterSource, rowMapper);
    }
}
